home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / presto / presto10.lha / src / process.C < prev    next >
C/C++ Source or Header  |  1991-12-11  |  17KB  |  678 lines

  1. //
  2. // process.c:
  3. //
  4. //      Implementation of process class.
  5. //
  6. //      Main routine p_wait is where each scheduling thread lives.
  7. //
  8. // Modification History:
  9. //
  10. //   05-Dec-91 Paul Barton-Davis
  11. //   Provided operator new() and operator delete() to replace old
  12. //   use of "this = 0" anachronism. The anachronism was already removed.
  13. //
  14. //   18-Jun-91 Paul Barton-Davis
  15. //   Root process ctor no longer sets affinity. This is done in 
  16. //   Scheduler::invoke, after all processes have been fork(2)-ed. 
  17. //   This should reduce the concurency reduction that results
  18. //   from the fact that affinity is maintained across a fork(2).
  19. //
  20. //   18-Jun-91 Paul Barton-Davis
  21. //   Parametized sizes of global thread freelist and local
  22. //   freelist spillover threshold. Would have been nice to have used
  23. //   something other than a global var for these, but its more work than
  24. //   is justified by the benefits.
  25. //
  26. //   12-Jan-90  John Faust
  27. //   Add support for processor affinity on Sequent Symmetry.
  28. //
  29. //   05-Dec-89  John Faust
  30. //   Remove all stack free lists.  Allocate stacks of fixed size when thread
  31. //   is allocated.  Stack remains associated with owning thread.  More
  32. //   efficient (removes search of stack freelist for stack of proper size,
  33. //   allocation of stack if one of proper size not found, and eliminates
  34. //   need to balance stack freelists).
  35. //
  36. //   30-Nov-1989  John Faust
  37. //   Incorporate Bob Sandstro fix which allows gprof monitor files to be
  38. //   captured.
  39. //
  40. //   16-Nov-1989  John Faust
  41. //   Implement per-processor free lists of stacks.
  42. //
  43. //   08-Nov-1989  John Faust
  44. //   Implement per-processor free lists of thread templates.
  45. //
  46.  
  47.  
  48. #define _PROCESS_C
  49.  
  50. #include <stddef.h>
  51. #include <sys/types.h>
  52. #include <signal.h>
  53. #include <osfcn.h>
  54. #include "presto.h"
  55.  
  56. #ifdef i386
  57. #include <sys/tmp_ctl.h>
  58. #endif /* i386 */
  59.  
  60. Process staticproc;
  61. Process *sysproc = &staticproc;
  62.  
  63. #ifdef GPROF
  64. extern char *_mon_file;
  65. static char mon_name[20];
  66. #endif /* GPROF */
  67.  
  68. private_t Process *thisproc = 0;    // always ME!
  69.  
  70. extern Main *MAIN;
  71.  
  72. //
  73. // This is the global free list of thread templates.  Deleted threads
  74. // go here when the local free list of the owning processor is full.
  75. // Threads are taken from here only when a local free list is exhausted.
  76. // The local lists (see process.h) are non-shared and are thus unlocked,
  77. // for speed.  The global list is shared and is thus locked.  That makes
  78. // it slow, so we only access it when we really have to.
  79. //
  80. static shared_t ThreadQ thread_global_freelist (TS_ANY);
  81.  
  82. shared_t int gbl_thread_freelist_max = GBL_THREAD_FREELIST_MAX;
  83. shared_t int lcl_thread_freelist_thresh = LCL_THREAD_FREELIST_THRESH;
  84.  
  85. //
  86. // This constructor is called to create the root process.
  87. //
  88. // ptag proc constructor is useful for getting a handle on the root
  89. // process.  Since we weren't around when he got forked, we kluge
  90. // with this.
  91. //
  92. Process::Process(int ptag, int id)
  93. {
  94.        SIG_TYP p_continue;        // signal handler
  95.        int i;
  96.        Thread* tlist [1+NUMPROCS+NUM_PREALLOC_THREADS];
  97.  
  98.     if (ptag != P_ROOT /* || no root exists */ )    {
  99.         error("Invalid attempt to flag root Process\n");
  100.     }
  101.  
  102.         //
  103.         //  Create process local thread freelist, and preallocate
  104.         //  some threads.
  105.         //
  106.     //  The root process is responsible for creating the
  107.     //  schuduler_starter thread as well as each of the main threads.
  108.     //  Therefore, preallocate enough extra threads (1 for the
  109.         //  scheduler_starter, one for each possible processor).
  110.     //
  111.     //  Be sure to use MAINSTACKSIZE for the main threads,
  112.     //  and STACKSIZE for the remaining preallocated threads.
  113.     //  For now, STACKSIZE is used for all preallocated threads,
  114.     //  and MAINSTACKSIZE ends up being ignored.
  115.         //
  116.         p_thread_freelist = new ThreadQUnlocked (TS_ANY);
  117.         for (i=0; i<1+NUMPROCS+NUM_PREALLOC_THREADS; i++)
  118.             tlist [i] = thisthread->newthread ("prealloc", 0, DEFSTACKSIZ);
  119.         for (i=0; i<1+NUMPROCS+NUM_PREALLOC_THREADS; i++)
  120.             free_thread (tlist[i]);    // put on local freelist
  121.  
  122.     p_id = id;
  123.     p_ppid = getppid();
  124.     p_pid = getpid();
  125.     p_name = "ROOT";
  126.     p_flags = P_ROOT;
  127.     p_state = S_RUN;        // obviously
  128.     p_request = 0;
  129.     p_thread = 0;
  130.     p_schedthread = thisthread;
  131.     thisproc = this;
  132.  
  133.     signal(SIGCONT, p_continue);
  134. }
  135.  
  136.  
  137. //
  138. //  This constructor is the one invoked by newprocess.  It creates all
  139. //  processes with the exception of the root process and the original
  140. //  static process.
  141. //
  142. Process::Process(char* name, int id, int delayedfork)
  143. {
  144.         int i;
  145.         Thread* tlist [NUM_PREALLOC_THREADS];
  146.  
  147.         //
  148.         //  Create process local thread freelist, and preallocate
  149.         //  some threads.
  150.         //
  151.         p_thread_freelist = new ThreadQUnlocked (TS_ANY);
  152.         for (i=0; i<NUM_PREALLOC_THREADS; i++)
  153.             tlist [i] = thisthread->newthread ("prealloc", 0, DEFSTACKSIZ);
  154.         for (i=0; i<NUM_PREALLOC_THREADS; i++)
  155.             free_thread (tlist[i]);    // put on local freelist
  156.  
  157.     p_name = name;
  158.     p_request = 0;
  159.     p_flags = 0;
  160.     p_id = id;
  161.     p_schedthread = p_thread = 0;
  162.     if  (!delayedfork) {
  163.         p_fork();
  164.         }
  165.     else {
  166.         p_state = S_DELAYEDFORK;
  167.         }
  168.     return;
  169. }
  170.  
  171. //
  172. // Constructor for staticproc (sysproc).
  173. //
  174. Process::Process()
  175. {
  176. #if (sun && THREAD_HAS_INTERRUPTIBLE_FIELD)
  177.     p_interruptible = 0;
  178. #endif
  179. #ifdef vax 
  180.     p_interruptible = 0;
  181. #endif /* vax */
  182. #ifdef mips
  183.     p_interruptible = 0;
  184. #endif
  185.     p_name = "sysproc";
  186.         p_thread_freelist = new ThreadQUnlocked (TS_ANY);
  187. }
  188.  
  189. //
  190. // Delay the fork until after the return of the constructor.  Derived
  191. // classes will need to take advantage of this to ensure that the
  192. // virtual table in the derived class is properly initalized.  Use
  193. // for a derived class is:
  194. //
  195. //    DerivedProcess::DerivedProcess(args) : (name, id,  S_DELAYEDFORK)
  196. //    {
  197. //        initialize derived part
  198. //        Process::p_fork();        
  199. //        /* only parent returns to here.  Child never does */
  200. //    }
  201. //
  202. // Must be careful to use private stack when forking into child; else
  203. // parent and child can race on the shared stack (leads to strange
  204. // core dumps -- hard to diagnose).  This should be cleaned up; use of
  205. // asm-functions may help.
  206.  
  207. void
  208. Process::p_fork()
  209. {
  210.     int pid;
  211.     int spinonfork = 1;        // hold child until done
  212.     static private_t int private_stack[256];
  213.  
  214.     extern int _rtmp;
  215.  
  216. #ifdef sun
  217.     _rtmp = (int) &private_stack[sizeof(private_stack) / sizeof(int)];
  218. #endif /* sun */
  219. #ifdef sequent
  220.     _rtmp = (int) &private_stack[sizeof(private_stack) / sizeof(int)];
  221. #endif /* sequent */
  222.  
  223. #ifdef mc68020
  224.     asm("movl sp, a0");
  225.     asm("movl __rtmp, sp");
  226.     asm("movl a0, __rtmp");
  227. #endif /* mc68020 */
  228. #ifdef    i386
  229.     asm("xchgl %esp, __rtmp");
  230. #endif /*    i386 */
  231. #ifdef    ns32000
  232.     asm("sprd sp, r0");
  233.     asm("lprd sp, __rtmp");
  234.     asm("movd r0, __rtmp");
  235. #endif /*    ns32000 */
  236.  
  237.     p_state = S_FORKING;
  238.  
  239.     pid = fork();
  240.     switch (pid)    {
  241.     case -1:    // fork error
  242. #ifdef mc68020
  243.         asm("movl __rtmp, sp");
  244. #endif /* mc68020 */
  245. #ifdef sequent
  246. #ifdef    i386
  247.         asm("movl __rtmp, %esp");
  248. #endif /*    i386 */
  249. #ifdef    ns32000
  250.         asm("lprd sp, __rtmp");
  251. #endif /*    ns32000 */
  252. #endif /* sequent  */
  253.         p_pid = -1;
  254.         return;    
  255.  
  256.  
  257.     case 0:        // child
  258.         p_ppid = getppid();
  259.         p_pid = getpid();
  260. #ifdef GPROF
  261.                 (void) sprintf (mon_name, "%s.%d", _mon_file, p_pid);
  262.                 _mon_file = mon_name;
  263. #endif /* GPROF */
  264.         p_runchild(&spinonfork);
  265.         // NOTREACHED
  266.         error("Process forked child returned???");
  267.  
  268.     default:    // parent: can't return until child finished with stack
  269. #ifdef mc68020
  270.         asm("movl __rtmp, sp");
  271. #endif /* mc68020 */
  272. #ifdef sequent
  273. #ifdef    i386
  274.         asm("movl __rtmp, %esp");
  275. #endif /*    i386 */
  276. #ifdef    ns32000
  277.         asm("lprd sp, __rtmp");
  278. #endif /*    ns32000 */
  279. #endif /* sequent */
  280.         p_pid = pid;
  281.         while (spinonfork)
  282.             continue;
  283.     }
  284. }
  285.  
  286.  
  287. //
  288. // Fake being able to virtualize the constructor
  289. //
  290. Process*
  291. Process::newprocess(char* name, int id)
  292. {
  293.     return new Process(name, id);
  294. }
  295.  
  296. // Global "wrapper function" for use in Thread::start() call.
  297. // Allows us to access a member function correctly, instead of by
  298. // hacking around the possibly mutable C++ calling convention.
  299.  
  300. start_Process (Process *p)
  301.  
  302. {
  303.   return p->invoke();
  304. }
  305.  
  306. //
  307. // Run the child scheduler.  Hold onto the parent until we get all
  308. // that we need from the args (this especially).  See comments.
  309. //
  310. void
  311. Process::p_runchild(int *spinonfork)
  312. {
  313.     extern int _rtmp;
  314.  
  315.         Thread* t = thisthread->newthread (p_name, 0, DEFSTACKSIZ);
  316.  
  317. #ifdef DEBUG_STARTUP
  318.         cout << "in p_runchild (after fork)\n";
  319. #endif /* DEBUG_STARTUP */
  320.  
  321.     thisthread = t;            //  get what we need from our parents
  322.     thisproc = this;        //  stack
  323.  
  324.     //
  325.     _rtmp = (int)(thisthread->stack()->top());
  326.     { 
  327. #ifdef vax
  328. //    asm("movl    __rtmp, sp");
  329. #endif
  330. #ifdef mc68020
  331.     asm("movl    __rtmp, sp");
  332. #endif /* mc68020 */
  333. #ifdef ns32000
  334.     asm("lprd    sp, __rtmp");
  335. #endif
  336. #ifdef    i386
  337.     asm("movl    __rtmp, %esp");
  338. #endif
  339.     }    
  340.     //
  341.     // should have secondary entry point into start to avoid the test
  342.     // for a scheduler.
  343.     //
  344.     //
  345.     thisthread->setflags(TF_SCHEDULER|TF_KEEPSTACK|TF_NONPREEMPTABLE);
  346.     thisthread->start(0, (PFany) start_Process, thisproc);
  347.     thisthread->setproc(thisproc);
  348.  
  349.     thisproc->p_schedthread = thisthread;
  350.     *spinonfork = 0;        // Let him go...
  351.     //
  352.     // The parent has just returned using the frame that our
  353.     // fp references.  This means that we can never return beyond
  354.     // this routine, AND we can't reference any of the params
  355.     // passed to us on the stack  (use thisthread and thisproc from
  356.     // here on).
  357.         //
  358.  
  359.         //
  360.         // Set processor affinity if applicable.
  361.         //
  362. #ifdef i386
  363.  
  364. #ifdef DEBUG_STARTUP
  365.         cout << form ("affinity = %d\n", MAIN->get_affinity()); cout.flush ();
  366. #endif /* DEBUG_STARTUP */
  367.         if (MAIN->get_affinity ())
  368.         {
  369.             if (tmp_affinity (thisproc->id()) == -1)
  370.                 cout << "unable to set affinity on process "
  371.                      << thisproc->id() << "\n";
  372. //            else
  373. //                cout << "affinity set on process "
  374. //                     << getpid() << " "
  375. //                     << thisproc->id() << "\n";
  376. //            cout.flush ();
  377.         }
  378. #endif /* i386 */
  379. #ifdef PROFILE
  380.     QProcInit(thisproc->id());
  381. #endif
  382.  
  383.     //
  384.     // Can't use run since it won't let us idle "thisthread" and run
  385.     // "thisthread" at the same time.
  386.     //
  387.     thisthread->isrunning();
  388.     thisthread->runrun();        // fall into p_wait
  389.     thisthread->isnotrunning();
  390.  
  391.     //
  392.     // fall out of p_wait on its return to here
  393.     //
  394.     delete thisproc;
  395.     //
  396.     // should never get here
  397.     //
  398.     error("PROCESS DESTRUCTOR RETURNED");
  399. }
  400.  
  401. //
  402. // ~Process:    kill a Process.
  403. //    If we are the process to be killed, then we mark ourselves as a 
  404. //    zombie and _exit()  (no destructors will be called).  If we are
  405. //    trying to destroy another process, then we mark it
  406. //    as S_EXITING and then ask the process to actually return.
  407. //    This will have it fall back into runrun and then into
  408. //    p_runchild, where we will get called to kill it running
  409. //    as the process which is being asked to die.
  410. //
  411. //    Doing it this way allow processes to perform whatever cleanup
  412. //    they feel like before actually disappearing.
  413. //
  414. //    If we are the root process, we just return quietly
  415. //    
  416. //
  417.  
  418. Process::~Process()
  419. {
  420.        if((this->p_state&S_EXITING) == 0)    {
  421.         int pid = p_pid;
  422.         if (this == thisproc)    {
  423.             this->p_state = S_ZOMBIE;
  424.             if (this->isroot())    {
  425.                 /* this = 0; */ // illegal anachronism
  426.                 return;
  427.             }
  428.             //
  429.             // Our stack frame is gonna be all screwed up here
  430.             // since we started off with the fp running
  431.             // on our parent's frame, and he has now return.
  432.             // We can never return from this routine.
  433.             //
  434. #ifdef GPROF
  435.                         monitor(0);
  436. #endif /* GPROF */
  437.             _exit(0);
  438.         } else    {
  439.             this->p_state = S_EXITING;
  440.             this->request(R_RETURN);
  441.         }
  442.     }
  443. }
  444.  
  445. int
  446. Process::invoke()
  447. {
  448.     p_wait();
  449.     return 0;
  450. }
  451.  
  452. //
  453. // Parent (or sibling) wakes up a looping Process here with the
  454. // "special" request code
  455. //
  456. int
  457. Process::request(int req)        
  458. {
  459.  
  460.     //
  461.     // If someone is stupid enough to make a request on a proc that
  462.     // is already servicing someone else... then they are just
  463.     // gonna have to wait their turn!
  464.     //
  465.     while (p_request != R_NULL)    {
  466.         if (p_request&(R_DIE|R_RETURN))    // no way to satisfy
  467.             return -1;
  468.     }
  469.  
  470.     p_request = req;
  471.  
  472.     if (p_state&S_OSPAUSE)    {    // sleeping in os
  473.         cerr << "\nWaking up " << this << "\n";
  474.         return (kill(p_pid, SIGCONT));
  475.     } else        
  476.         return 0;
  477. }
  478.  
  479.  
  480. //
  481. // p_wait:    hang around and wait for something interesting
  482. //        to happen. That is, loop until someone bangs
  483. //        on our door, or until there is a readythread to
  484. //        start working on, OR we are not the root process, but our
  485. //        parent process seems to have disappeared (in which case
  486. //        we abort the scheduler, killing ourselves and all our 
  487. //        siblings).  We only check the last case "every so often" when 
  488. //        can't find anything else to do.
  489. //        This is an example of a "heuristic."  AI in action!
  490. //
  491. //        This doesn't guarantee that the system will always stop.  If
  492. //        the parent dies of as the result of an uncaught signal while
  493. //        holding a spinlock, the rest of the system could be blocked.
  494. //        If all other process are blocked, then the system will
  495. //        spin forever waiting for the holding process to relase
  496. //        the spinlock (which will never happend).  Lesson:
  497. //            Don't kill -9 the root process.
  498. //
  499. void
  500. Process::p_wait()
  501. {
  502.     int idlespan = 0;    
  503.  
  504. #ifdef PROFILE
  505.     QIdleLoopBegin();
  506. #endif
  507.  
  508.     for (;;)    {
  509.         p_state = S_WAIT;
  510.         // wait until readythread, or until we get asynch request
  511.         if ( (p_request == NULL) && (p_thread = sched->getreadythread()) == NULL)    {
  512.              if (idlespan++ == 50000)    {
  513.                  // check if our parent has died and we are not root
  514.             if (!isroot() && getppid() != this->ppid())    {
  515.                 // kill myself and all siblings
  516.                 sched->abort(-SIGKILL);
  517.             } else    
  518.                 idlespan = 0;
  519.              }
  520.              continue;
  521.         }
  522.  
  523.         if (p_request)    {
  524.             //
  525.             // assumption is that only one thread can be diddling
  526.             // with processes at a time... otherwise this might
  527.             // not work.
  528.             //
  529.  
  530.             if (p_request & R_RETURN)    {
  531. //                if ( (p_flags&P_ROOT) == 0)
  532. //                    error("PROCS CANT RETURN YET\n");
  533. //                else
  534.                     return;
  535.             }
  536.  
  537.             //
  538.             // They can only die
  539.             //
  540.             if (p_request & R_DIE)        {    
  541.                 delete this;
  542.                 // not reached! 
  543.             }
  544.  
  545.             if (p_request & R_PARK)    {
  546.                 this->p_pause();
  547.                 continue;
  548.             };
  549.         } else    {        // must have a readythread
  550.             if (p_thread->flags()&TF_SCHEDULER)    {    
  551.                 p_thread->error("Can't schedule a scheduling thread");
  552.                 continue;        // NOT REACHED?
  553.             }
  554.             p_state = S_RUN;
  555.             (void)p_thread->run();    
  556.         }
  557.         // others
  558.     }
  559. }    
  560.  
  561.  
  562. //
  563. // p_pause:    internal version of park
  564. //
  565. void
  566. Process::p_pause()
  567. {
  568.     if (p_state != S_WAIT)    
  569.         error("p_pause called to pause non spinning process");
  570.  
  571.     p_state = S_OSPAUSE;
  572.     p_request = 0;        // must clear here, not above
  573.     ::pause();
  574.     p_state = S_WAIT;
  575. }
  576.  
  577. //
  578. // park:    Give it a rest buddy boy
  579. //
  580. void
  581. Process::park()
  582. {
  583.     if (this == thisproc)    {
  584.         cerr << "Warning: putting myself to sleep\n";
  585.         this->p_pause();
  586.     }
  587.     else    {
  588.         // baby you can drive my car
  589.         p_request = R_WAKEUP|R_PARK;
  590.     }
  591. }
  592.  
  593. void
  594. Process::drive()
  595. {
  596.     if (this == thisproc)
  597.         return;
  598.     else    {
  599.         if (p_state != S_OSPAUSE)
  600.             cerr << "Warning: proc not parked\n";
  601.         ::kill(p_pid, SIGCONT);
  602.     }
  603. }
  604.  
  605.  
  606. void
  607. Process::error(char *s)
  608. {
  609.     cerr << "Process error " << s << "  " << this << "\n";
  610.     fatalerror();
  611. }
  612.  
  613. // signal handler
  614. SIG_TYP p_continue()
  615. {
  616.     return 0;
  617. }
  618.  
  619.  
  620. //
  621. // A process comes here when it's local thread freelist is empty.
  622. // Get any extra threads that are lying around in the global thread freelist.
  623. // Could optimize to lock global list and grab all threads before unlock,
  624. // instead of doing lock-get-unlock for each thread.
  625. //
  626. void
  627. Process::get_gbl_threads ()
  628. {
  629.     register Thread* t;
  630.     int i;
  631.  
  632.     if (thread_global_freelist.length() == 0) return;
  633.     for (i=0; i<lcl_thread_freelist_thresh/2-1; i++)
  634.     {
  635.         t = thread_global_freelist.get ();
  636.         if (t == 0) break;
  637.         p_thread_freelist->append (t);
  638.     }
  639. }
  640.  
  641. //
  642. // A process comes here when it's local thread freelist is too full.
  643. // Put some of the extra threads into the global thread freelist.
  644. // Could optimize to lock global list and append all extras before unlock,
  645. // instead of doing lock-append-unlock for each thread.
  646. //
  647. void
  648. Process::free_gbl_threads ()
  649. {
  650.     Thread* t;
  651.     int i;
  652.  
  653.     for (i=p_thread_freelist->length(); i > lcl_thread_freelist_thresh/2; i--)
  654.     {
  655.         t = p_thread_freelist->get ();
  656.  
  657.         if (t == 0) 
  658.     {
  659.         break;
  660.     }
  661.         else if (thread_global_freelist.length() > gbl_thread_freelist_max)
  662.     {
  663.             delete t;
  664.     }
  665.         else
  666.     {
  667.             thread_global_freelist.append (t);
  668.     }
  669.     }
  670. }
  671.  
  672.  
  673. void
  674. Process::print(ostream& s)
  675. {
  676.     s << form("(Process)=0x%x, p_id=%d, p_name=%s, p_pid=%d, p_ppid=%d, p_state=0x%x, p_request=%d",this,p_id,p_name,p_pid,p_ppid,p_state,p_request);
  677. }
  678.